package control.macro
{
	import events.WorldEvent;
	import flash.display.Stage;
	import flash.events.KeyboardEvent;
	import model.macro.Armor;
	import model.macro.FortressType;
	import model.macro.Player;
	import model.macro.Territory;
	import model.macro.Unit;
	import model.macro.Weapon;
	import model.macro.World;
	import view.macro.MapSprite;
	import view.micro.background.BattleBackgroundSprite;
	
	/**
	 */
	public class HumanWorldController
	{
		static public const K_SELECT_ALL_UNITS:int = 85; // U
		static public const K_BUILD_SWORDSMAN:int = 66; // B
		static public const K_BUILD_CASTLE:int = 70 // F
		static public const K_END_TURN:int = 32 // Space
		
		protected var keys:Array;
		private var world:World;
		private var selected_territory:Territory;
		private var selected_units:Vector.<Unit>;
		private var _player:Player; // Player this human controller is attached to
		
		public function HumanWorldController(player:Player, world:World, stage:Stage)
		{
			_player = player;
			this.world = world;
			
			keys = new Array();
			
			selected_units = new Vector.<Unit>();
			
			stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
			stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
			
			world.addEventListener(WorldEvent.TERRITORY_SELECTED, onTerritorySelected);
			world.addEventListener(WorldEvent.TERRITORY_RIGHT_CLICKED, onTerritoryRightClick);
			world.addEventListener(WorldEvent.UNIT_SELECTED, onUnitSelected);
			world.addEventListener(WorldEvent.UNIT_DESELECTED, onUnitDeselected);
			world.addEventListener(WorldEvent.ALL_UNITS_DESELECTED, onAllUnitsDeselected);
			world.addEventListener(WorldEvent.UNITS_MOVED, onUnitsMoved);
		}
		
		private function onUnitsMoved(e:WorldEvent):void 
		{
			world.dispatchEvent(new WorldEvent(WorldEvent.ALL_UNITS_DESELECTED, world));
		}
		
		private function onUnitSelected(e:WorldEvent):void
		{
			if ((e.data as Unit).owner == world.current_player)
				this.selected_units.push((e.data as Unit));
		}
		
		private function onUnitDeselected(e:WorldEvent):void
		{
			this.selected_units.splice(this.selected_units.indexOf(e.data as Unit), 1);
		}
		
		private function onAllUnitsDeselected(e:WorldEvent):void
		{
			this.selected_units.length = 0;
		}
		
		private function onTerritorySelected(e:WorldEvent):void
		{
			if ((e.data as Territory) != this.selected_territory)
			{
				world.dispatchEvent(new WorldEvent(WorldEvent.ALL_UNITS_DESELECTED, world));
			}
			this.selected_territory = (e.data as Territory);
			if (this.selected_territory == null)
			{
				throw new Error("CAST TO TERRITORY FAILED: " + e.data);
			}
			trace("Territory Selected: " + this.selected_territory);
		}
		
		private function onTerritoryRightClick(e:WorldEvent):void
		{
			if (selected_territory != null)
			{
				if (selected_territory.isAdjacent(e.data as Territory) && world.current_player == player)
				{
					var movable:Boolean = true;
					for each (var unit:Unit in selected_units) 
					{
						if (unit.moves_remaining <= 0)
							movable = false;
					}
					if (movable) 
					{
						world.moveUnits(selected_territory, selected_units, e.data as Territory);
						world.dispatchEvent(new WorldEvent(WorldEvent.ALL_UNITS_DESELECTED, world));
					} else {
						// TODO: Make error event?
						trace("Some selected units cannot move. Try using the select all movable command");
					}
				}
				else
				{
					// What to tell the user? Also, how to tell the user? We only have a stage and no HUD access... Ummm...
					trace("Yo, can't move that there");
				}
			}
		}
		
		/**
		 * Handle keydown events.
		 * @param	e	the event
		 */
		protected function onKeyDown(e:KeyboardEvent):void
		{
			keys[e.keyCode] = true;
			
			switch (e.keyCode)
			{
				case K_SELECT_ALL_UNITS: // U
					if (selected_territory != null)
					{
						trace("Selected Territory: " + selected_territory + "||Unit vector length = " + selected_territory.units.length);
						for each (var unit:Unit in selected_territory.units)
						{
							world.dispatchEvent(new WorldEvent(WorldEvent.UNIT_SELECTED, world, unit));
						}
					}
					break;
				case K_BUILD_SWORDSMAN: // B
					if (selected_territory != null)
					{
						if (world.current_player == player)
						{
							player.buildUnit(selected_territory, Weapon.SWORD, Armor.CLOTH);
						} 
						else
						{
							// TODO: Make more error events.
							trace("That's not yours.");
						}
					}
					break;
				case K_BUILD_CASTLE: // F
					if (selected_territory != null)
					{
						if (world.current_player == player)
						{
							player.buildFortress(selected_territory, FortressType.CASTLE);
						} 
						else
						{
							trace("That's not yours.");
						}
					}
					break;
				case K_END_TURN: // Space
					world.nextTurn();
					break;
			}
		}
		
		/**
		 * Handle keyup events
		 * @param	e	the event
		 */
		protected function onKeyUp(e:KeyboardEvent):void
		{
			keys[e.keyCode] = false;
		}
		
		public function get player():Player 
		{
			return _player;
		}
	}
}